(define (empty-env) 
    `()
)


(define (empty-env? env) 
    (null? env)
)


(define (extend-env var val env)
    (list
        (list 
            (list var)
            (list val)
        )
        env
    )
)


(define (apply-env env search-var)
    (if (empty-env? env)
        (report-no-binding-found)
        (let
            (
                (result 
                    (get-value (caar env) (cadar env) search-var)
                )
            )
            (if (eqv? (car result) #t)
                (cadr result)
                (apply-env (cdr env) search-var)
            )
        )
    )
)


(define (get-value vars vals search-var)
    (cond 
        ((null? var) (list #f `())
        ((eqv? (car vars) search-var) (car vals))
        (else 
            (get-value 
                (cdr vars)
                (cdr vals)
                search-var
            )
        )
    )
)


(define (report-no-binding-found search-var)
    (eopl:error ’apply-env "No binding for ~s" search-var)
)


(define (report-invalid-env env)
    (eopl:error ’apply-env "Bad environment: ~s" env)
)


(define (extend-env* var-list val-list env)
    (if (null? var-list)
        (report-invalid-variables-or-values)
        (list
            (list var-list val-list)
            env
        )
    )
)


(define (report-invalid-variables-or-values)
    (eopl:error ’extend-env* "Bad variables or values" )
)


(display
    (extend-env `c 3
        (extend-env `c 3
            (extend-env `b 2
                (extend-env `a 1 
                    (empty-env)
                )
            )
        )
    )
)
